package com.foreveross.proxyip.core.zk.task;

import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.mortbay.log.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dayatang.domain.InstanceFactory;
import com.foreveross.proxyip.core.pools.AvailablePool;
import com.foreveross.proxyip.core.pools.DbPool;
import com.foreveross.proxyip.core.pools.PoolsManager;
import com.foreveross.proxyip.core.pools.PublicPool;
import com.foreveross.proxyip.core.redis.RedisExecutor;
import com.foreveross.proxyip.core.redis.RedisManager;
import com.foreveross.proxyip.core.zk.ZkAppCenter;
import com.foreveross.proxyip.util.SerializeUtil;

public abstract class ZkTask {
	
	protected Logger log = LoggerFactory.getLogger(this.getClass());
	
	protected PoolsManager poolsManager = InstanceFactory.getInstance(PoolsManager.class);
	
	protected RedisManager redisManager = RedisManager.getInstance();
	/**
	 * 任务执行者
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public int execute(Map<String, Object> params) throws Exception {
		String taskParams = params.get("taskParams").toString();
		Map<String, String> plans = (Map<String, String>) params.get("plans");
		String app = ZkAppCenter.getInstance().appName;
		app = app.substring(app.lastIndexOf("/") + 1);
		String planKey = null;
		
		for (Entry<String, String> entry : plans.entrySet()) {
			if (entry.getKey().contains(app)) {
				planKey = entry.getValue();
				break;
			}
		}
		
		final String key = planKey;
		
		try {
			byte[] taskNumBt = new RedisExecutor<byte[]>() {
				@Override
				public byte[] run() throws Exception {
					byte[] redisVal = this.jedis.get(key.getBytes());
					this.jedis.del(key.getBytes());
					
					return redisVal;
				}
			}.exec();
			
			if (taskNumBt == null || taskNumBt.length == 0
					|| breakTask(taskParams)) {
				return -1;
			}
			Long[] taskNums = (Long[]) SerializeUtil.unserialize(taskNumBt);
			return exec(taskNums, taskParams);
		} catch (Exception e) {
			Log.info("task execute error!!");
			return -1;
		}
	}

	protected String getPlanKey(String taskParams) {
		return taskParams+"_plan";
	}
	
	protected AvailablePool getPool(String taskParams) {
		AvailablePool pool;
		if(taskParams.contains(PublicPool.POOL_CODE)){
			pool = poolsManager.getPublicPool();
		}else if(taskParams.contains(DbPool.POOL_CODE)){
			pool = poolsManager.getDbPool();
		}else{
			pool = poolsManager.getChannelPoolMap().get(StringUtils.substringBefore(taskParams, "_"));
		}
		return pool;
	}
	
	
	public abstract boolean breakTask(String taskParams) throws Exception;
	
	public abstract int exec(Long[] taskNums,String taskParams) throws Exception;

}
